package com.lau.dicttranslator.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 缓存工具类
 * 提供便捷的Redis缓存操作
 */
@Component
@Slf4j
public class CacheUtil {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    /**
     * 设置缓存（带过期时间）
     */
    public void set(String key, String value, long expireSeconds) {
        try {
            if (expireSeconds > 0) {
                redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(expireSeconds));
                log.debug("缓存设置成功: key={}, value={}, expire={}s", key, value, expireSeconds);
            } else {
                redisTemplate.opsForValue().set(key, value);
                log.debug("缓存设置成功（永不过期）: key={}, value={}", key, value);
            }
        } catch (Exception e) {
            log.error("设置缓存失败: key={}", key, e);
        }
    }
    
    /**
     * 设置缓存（永不过期）
     */
    public void set(String key, String value) {
        set(key, value, -1);
    }
    
    /**
     * 获取缓存
     */
    public String get(String key) {
        try {
            String value = redisTemplate.opsForValue().get(key);
            if (value != null) {
                log.debug("缓存命中: key={}, value={}", key, value);
            } else {
                log.debug("缓存未命中: key={}", key);
            }
            return value;
        } catch (Exception e) {
            log.error("获取缓存失败: key={}", key, e);
            return null;
        }
    }
    
    /**
     * 删除缓存
     */
    public boolean delete(String key) {
        try {
            Boolean result = redisTemplate.delete(key);
            log.debug("删除缓存: key={}, result={}", key, result);
            return Boolean.TRUE.equals(result);
        } catch (Exception e) {
            log.error("删除缓存失败: key={}", key, e);
            return false;
        }
    }
    
    /**
     * 批量删除缓存
     */
    public long delete(Set<String> keys) {
        try {
            Long result = redisTemplate.delete(keys);
            log.debug("批量删除缓存: keys={}, count={}", keys.size(), result);
            return result != null ? result : 0;
        } catch (Exception e) {
            log.error("批量删除缓存失败: keys={}", keys.size(), e);
            return 0;
        }
    }
    
    /**
     * 检查缓存是否存在
     */
    public boolean exists(String key) {
        try {
            Boolean result = redisTemplate.hasKey(key);
            return Boolean.TRUE.equals(result);
        } catch (Exception e) {
            log.error("检查缓存存在性失败: key={}", key, e);
            return false;
        }
    }
    
    /**
     * 设置缓存过期时间
     */
    public boolean expire(String key, long expireSeconds) {
        try {
            Boolean result = redisTemplate.expire(key, Duration.ofSeconds(expireSeconds));
            log.debug("设置缓存过期时间: key={}, expire={}s, result={}", key, expireSeconds, result);
            return Boolean.TRUE.equals(result);
        } catch (Exception e) {
            log.error("设置缓存过期时间失败: key={}", key, e);
            return false;
        }
    }
    
    /**
     * 获取缓存剩余过期时间
     */
    public long getExpire(String key) {
        try {
            Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
            return expire != null ? expire : -1;
        } catch (Exception e) {
            log.error("获取缓存过期时间失败: key={}", key, e);
            return -1;
        }
    }
    
    /**
     * 根据模式获取所有匹配的键
     */
    public Set<String> keys(String pattern) {
        try {
            Set<String> keys = redisTemplate.keys(pattern);
            log.debug("模式匹配缓存键: pattern={}, count={}", pattern, keys != null ? keys.size() : 0);
            return keys;
        } catch (Exception e) {
            log.error("获取匹配键失败: pattern={}", pattern, e);
            return new HashSet<>();
        }
    }
    
    /**
     * 根据模式删除所有匹配的缓存
     */
    public long deleteByPattern(String pattern) {
        try {
            Set<String> keys = keys(pattern);
            if (keys != null && !keys.isEmpty()) {
                return delete(keys);
            }
            return 0;
        } catch (Exception e) {
            log.error("按模式删除缓存失败: pattern={}", pattern, e);
            return 0;
        }
    }
    
    /**
     * 获取缓存统计信息
     */
    public CacheStats getCacheStats(String keyPrefix) {
        try {
            Set<String> keys = keys(keyPrefix + "*");
            if (keys == null || keys.isEmpty()) {
                return new CacheStats(0, 0, 0);
            }
            
            long totalKeys = keys.size();
            long expiredKeys = 0;
            long totalExpireTime = 0;
            
            for (String key : keys) {
                long expire = getExpire(key);
                if (expire > 0) {
                    totalExpireTime += expire;
                } else if (expire == 0) {
                    expiredKeys++;
                }
            }
            
            return new CacheStats(totalKeys, expiredKeys, totalExpireTime);
        } catch (Exception e) {
            log.error("获取缓存统计失败: keyPrefix={}", keyPrefix, e);
            return new CacheStats(0, 0, 0);
        }
    }
    
    /**
     * 缓存统计信息
     */
    public static class CacheStats {
        private final long totalKeys;
        private final long expiredKeys;
        private final long totalExpireTime;
        
        public CacheStats(long totalKeys, long expiredKeys, long totalExpireTime) {
            this.totalKeys = totalKeys;
            this.expiredKeys = expiredKeys;
            this.totalExpireTime = totalExpireTime;
        }
        
        public long getTotalKeys() { return totalKeys; }
        public long getExpiredKeys() { return expiredKeys; }
        public long getTotalExpireTime() { return totalExpireTime; }
        public long getActiveKeys() { return totalKeys - expiredKeys; }
        public double getAverageExpireTime() { 
            return totalKeys > 0 ? (double) totalExpireTime / totalKeys : 0; 
        }
        
        @Override
        public String toString() {
            return String.format("CacheStats{totalKeys=%d, activeKeys=%d, expiredKeys=%d, avgExpireTime=%.1fs}", 
                    totalKeys, getActiveKeys(), expiredKeys, getAverageExpireTime());
        }
    }
} 